package com.zt.bigdata.elasticsearch.entity;

import com.google.common.collect.Lists;
import com.zt.bigdata.elasticsearch.utils.transport.ESClient;
import com.zt.bigdata.util.JsonHelper;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.client.transport.TransportClient;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

/**
 * "blob": {
 * "type": "binary"
 * },
 * "city": {
 * "type": "keyword"
 * },
 * "expected_attendees": {
 * "type": "integer_range"
 * },
 * "ip_addr": {
 * "type": "ip"
 * },
 * "is_published": {
 * "type": "boolean"
 * },
 * "location": {
 * "type": "geo_point"
 * },
 * "manager": {
 * "properties": {
 * "age": {
 * "type": "integer"
 * },
 * "name": {
 * "properties": {
 * "first": {
 * "type": "text"
 * },
 * "last": {
 * "type": "text"
 * }
 * }
 * }
 * }
 * },
 * "message": {
 * "type": "text",
 * "analyzer": "my_ik",
 * "search_analyzer": "ik_max_word"
 * },
 * "nation": {
 * "type": "keyword"
 * },
 * "number_of_bytes": {
 * "type": "integer"
 * },
 * "price": {
 * "type": "scaled_float",
 * "scaling_factor": 100
 * },
 * "state": {
 * "type": "keyword"
 * },
 * "time": {
 * "type": "date",
 * "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
 * },
 * "time_frame": {
 * "type": "date_range",
 * "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
 * },
 * "time_in_seconds": {
 * "type": "float"
 * },
 * "user": {
 * "type": "nested"
 * }
 * }
 */
public class AllField {
    private String blob;
    private String city;
    private String nation;
    private String state;
    private ExpectedAttendees expected_attendees;
    private String ip_addr;
    private boolean is_published;
    private Location location;
    private Manager manager;
    private String message;
    private Integer number_of_bytes;
    private float price;
    private long time;
    private ExpectedAttendees time_frame;
    private float time_in_seconds;
    private Name[] user;
    private List<Desc> descs;

    /**
     * private String blob;
     * private String city;
     * private String nation;
     * private String state;
     * private ExpectedAttendees expected_attendees;
     * private String ip_addr;
     * private boolean is_published;
     * private Location location;
     * private Manager manager;
     * private String message;
     * private Integer number_of_bytes;
     * private float price;
     * private long time;
     * private ExpectedAttendees time_frame;
     * private float time_in_seconds;
     * private Name[] user;
     * private List<Desc> descs;
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {


        String[] ips = "56.23.52.41,61.53.135.204,61.53.135.204,62.164.192.64,62.164.192.95,69.240.0.0,69.243.255.255,69.245.0.0,69.249.255.255,84.235.122.0,84.235.122.255,140.233.0.0,140.233.255.255,158.94.130.0,158.94.130.255,193.131.96.0,193.131.96.15,194.73.120.0,194.73.123.255,194.82.252.0,194.82.254.255,194.83.68.128,194.83.68.191,194.129.189.128,194.129.189.255,194.129.210.128,194.129.210.255,194.131.183.0,194.131.183.255".split(",");
        String[] nations = "china,america,uk".split(",");
        Map<String, Map<String, List<String>>> map = new HashMap<>();

        Map<String, List<String>> map1 = new HashMap<>();
        map1.put("zhejiang", Lists.newArrayList("hangzhou", "lishui", "ningbo"));
        map1.put("jiangsu", Lists.newArrayList("suzhou", "nanjing", "wuxi"));
        map1.put("guangdong", Lists.newArrayList("guangzhou", "zhuhai", "shenzhen"));
        map.put("china", map1);

        map1 = new HashMap<>();
        map1.put("Alaska", Lists.newArrayList("Juneau", "Anchorage", "Fairbanks"));
        map1.put("Arizona", Lists.newArrayList("Phoenix", "Tucson", "Mesa"));
        map1.put("Arkansas", Lists.newArrayList("Little Rock", "Fayetteville", "Houston"));
        map.put("america", map1);

        map1 = new HashMap<>();
        map1.put("scotland", Lists.newArrayList("Aberdeen", "Dundee", "Edinburgh"));
        map1.put("northern ireland", Lists.newArrayList("Belfast", "Durham", "Darlington"));
        map1.put("north west", Lists.newArrayList("Manchester", "Oldham", "Wigan"));
        map.put("uk", map1);

        ExpectedAttendees[] expectedAttendees = new ExpectedAttendees[]{
                new ExpectedAttendees(10, 20), new ExpectedAttendees(20, 30),
                new ExpectedAttendees(30, 40)
        };

        ArrayList<Location> locations = Arrays.stream("120.17,30.25;120.17,30.28;120.2,30.27;120.13,30.32;120.13,30.27;120.2,30.2;120.27,30.17;120.3,30.42;119.67,29.8;119.03,29.6;119.28,29.48;119.95,30.05;119.72,30.23"
                .split(";"))
                .map(x -> x.split(","))
                .map(x -> new Location(Double.valueOf(x[1]), Double.valueOf(x[0])))
                .collect(
                        ArrayList::new, ArrayList::add, ArrayList::addAll);

        Manager[] managers = new Manager[]{
                new Manager(30, new Name("tong", "zhang")),
                new Manager(25, new Name("xiaodan", "xuan")),
                new Manager(13, new Name("xiaoqing", "xuan"))

        };

        String messages[] = new String[]{
                "这是我发的第一条微博，很高兴认识大家",
                "英国零售业巨头陷入财务困境 计划关闭50家门店",
                "盛世创富：硫酸价格飞涨 有色冶炼企业成最大赢家",
                "在叙获释日本记者回国谈受虐经历：出声就是间谍"
        };
        LocalDateTime localDateTime2 = LocalDateTime.now();
        localDateTime2.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        Random random = new Random();

        long[] dates = new long[10];
        for (int i = 0; i < 10; i++) {
            int day = random.nextInt(100);
            dates[i] = localDateTime2.minusHours(day).toInstant(ZoneOffset.of("+8")).toEpochMilli();
        }

        Name[] users = new Name[]{
                new Name("tong", "zhang"),
                new Name("xiaodan", "xuan"),
                new Name("xiaoqing", "xuan")
        };

        List<Desc> descs = Lists.newArrayList(
                new Desc("prog_list", "programming list"),
                new Desc("cool_list", "cool stuff list")
        );


        ESClient esClient = new ESClient("my-application", "localhost:9300");
        TransportClient client = esClient.getClient();
        BulkRequestBuilder builder = client.prepareBulk();

        int batch = 0;
        for (int i = 0; i < 10000; i++) {


            AllField allField = new AllField();
            allField.setBlob("U29tZSBiaW5hcnkgYmxvYg==");

            String nation = nations[random.nextInt(100) % 3];
            allField.setNation(nation);
            String state = (String) map.get(nation).keySet().toArray()[random.nextInt(100) % 3];
            allField.setState(state);
            allField.setCity((String) map.get(nation).get(state).toArray()[random.nextInt(100) % 3]);


            allField.setExpected_attendees(new ExpectedAttendees(10, 20));

            allField.setExpected_attendees(expectedAttendees[random.nextInt(100) % 3]);

            allField.setTime_frame(new ExpectedAttendees("2015-10-31 12:00:00", "2015-11-01"));

            allField.setIp_addr(ips[random.nextInt(10000) % ips.length]);

            allField.setIs_published(random.nextInt(100) % 2 == 0);

            allField.setLocation(locations.get(random.nextInt(10000) % locations.size()));

            allField.setManager(managers[random.nextInt(100) % 3]);

            allField.setMessage(messages[random.nextInt(100) % 4]);

            allField.setNumber_of_bytes(random.nextInt(10000));

            allField.setPrice(random.nextFloat() * 10000);

            allField.setTime(dates[random.nextInt(10000) % 10]);

            allField.setTime_in_seconds(random.nextFloat() * 1000);

            allField.setUser(new Name[]{new Name("tong", "zhang"), new Name("xiaodan", "xuan"), new Name("xiaoqin", "xuan")});

            allField.setDescs(Lists.newArrayList(
                    new Desc("prog_list", "programming list"),
                    new Desc("cool_list", "cool stuff list")
            ));


//            System.out.println(allField);

            builder.add(
                    client.prepareIndex("my_all_field", "_doc", String.valueOf(i + 1))
                            .setSource(
                                    allField.toString().getBytes()
                            )
            );

            batch++;
            if (batch == 1000) {
                BulkResponse bulkResponse = builder.get();
                if (bulkResponse.hasFailures()) {
                    System.out.println(bulkResponse.buildFailureMessage());
                } else {

                }
                System.out.println("batch: " + batch);
                builder = client.prepareBulk();
                batch = 0;
            }
        }
        if (batch != 0) {
            BulkResponse bulkResponse = builder.get();
            if (bulkResponse.hasFailures()) {
                System.out.println(bulkResponse.buildFailureMessage());
            } else {

            }
        }


    }

    public String getBlob() {
        return blob;
    }

    public void setBlob(String blob) {
        this.blob = blob;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getNation() {
        return nation;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public ExpectedAttendees getExpected_attendees() {
        return expected_attendees;
    }

    public void setExpected_attendees(ExpectedAttendees expected_attendees) {
        this.expected_attendees = expected_attendees;
    }

    public String getIp_addr() {
        return ip_addr;
    }

    public void setIp_addr(String ip_addr) {
        this.ip_addr = ip_addr;
    }

    public boolean isIs_published() {
        return is_published;
    }

    public void setIs_published(boolean is_published) {
        this.is_published = is_published;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    public Manager getManager() {
        return manager;
    }

    public void setManager(Manager manager) {
        this.manager = manager;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Integer getNumber_of_bytes() {
        return number_of_bytes;
    }

    public void setNumber_of_bytes(Integer number_of_bytes) {
        this.number_of_bytes = number_of_bytes;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    public ExpectedAttendees getTime_frame() {
        return time_frame;
    }

    public void setTime_frame(ExpectedAttendees time_frame) {
        this.time_frame = time_frame;
    }

    public float getTime_in_seconds() {
        return time_in_seconds;
    }

    public void setTime_in_seconds(float time_in_seconds) {
        this.time_in_seconds = time_in_seconds;
    }

    public Name[] getUser() {
        return user;
    }

    public void setUser(Name[] user) {
        this.user = user;
    }

    public List<Desc> getDescs() {
        return descs;
    }

    public void setDescs(List<Desc> descs) {
        this.descs = descs;
    }

    @Override
    public String toString() {
        JsonHelper jsonHelper = new JsonHelper();
        return jsonHelper.toJsonString(this);
    }

    static class ExpectedAttendees<T> {
        private T gte;
        private T lte;

        public ExpectedAttendees(T gte, T lte) {
            this.gte = gte;
            this.lte = lte;
        }

        public T getGte() {
            return gte;
        }

        public void setGte(T gte) {
            this.gte = gte;
        }

        public T getLte() {
            return lte;
        }

        public void setLte(T lte) {
            this.lte = lte;
        }
    }

    static class Location {
        private double lat;
        private double lon;

        public Location(double lat, double lon) {
            this.lat = lat;
            this.lon = lon;
        }

        public double getLat() {
            return lat;
        }

        public void setLat(double lat) {
            this.lat = lat;
        }

        public double getLon() {
            return lon;
        }

        public void setLon(double lon) {
            this.lon = lon;
        }
    }

    static class Manager {
        private Integer age;
        private Name name;

        public Manager(Integer age, Name name) {
            this.age = age;
            this.name = name;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public Name getName() {
            return name;
        }

        public void setName(Name name) {
            this.name = name;
        }
    }

    static class Name {
        String first;
        String last;

        public Name(String first, String last) {
            this.first = first;
            this.last = last;
        }

        public String getFirst() {
            return first;
        }

        public void setFirst(String first) {
            this.first = first;
        }

        public String getLast() {
            return last;
        }

        public void setLast(String last) {
            this.last = last;
        }
    }

    static class Desc {
        String name;
        String description;

        public Desc(String name, String description) {
            this.name = name;
            this.description = description;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }
    }
}
